package com.jinmdz.fmis.common.util.third;

import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

/**
 * Pinyin4j 工具类
 * (源自网络)
 *
 * @author LiCongLu
 * @date 2020-01-20 08:58
 */
public final class Pinyin4jUtil {

    /**
     * 分隔符
     */
    public static final String delimiter = ",";

    /**
     * 获取中文汉字拼音 默认输出
     *
     * @param chinese 汉字字符串
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:04
     */
    public static String getPinyin(String chinese) {
        String pinyin = getPinyinZh_CN(makeStringByStringSet(chinese));
        if (pinyin != null && pinyin.contains(delimiter)) {
            return deDuplication(pinyin);
        }
        return pinyin;
    }

    /**
     * 去除重复
     *
     * @param pinyin
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:04
     */
    private static String deDuplication(String pinyin) {
        String[] strings = pinyin.split(delimiter);
        // 去重
        ArrayList<String> arrayList = new ArrayList<>();
        for (int i = 0; i < strings.length; i++) {
            if (!arrayList.contains(strings[i])) {
                arrayList.add(strings[i]);
            }
        }
        // 拼接
        StringBuilder builder = new StringBuilder();
        for (String string : arrayList) {
            if (builder.length() == 0) {
                builder.append(string);
            } else {
                builder.append(delimiter + string);
            }
        }
        return builder.toString();
    }

    /**
     * 拼音大写输出
     *
     * @param chinese 汉字字符串
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:04
     */
    public static String getPinyinToUpperCase(String chinese) {
        return getPinyin(chinese).toUpperCase();
    }

    /**
     * 拼音小写输出
     *
     * @param chinese 汉字字符串
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:04
     */
    public static String getPinyinToLowerCase(String chinese) {
        return getPinyin(chinese).toLowerCase();
    }

    /**
     * 首字母大写输出
     *
     * @param chinese 汉字字符串
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:03
     */
    public static String getPinyinFirstToUpperCase(String chinese) {
        return getPinyin(chinese);
    }

    /**
     * 拼音简拼输出
     * 即拼音首字母小写
     *
     * @param chinese 汉字字符串
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:03
     */
    public static String getPinyinAbbr(String chinese) {
        String abbr = getPinyinConvertAbbr(getPinyin(chinese));
        if (abbr != null && abbr.contains(delimiter)) {
            return deDuplication(abbr);
        }
        return abbr;
    }

    /**
     * 拼音简拼输出
     * 即拼音首字母小写
     *
     * @param chinese 汉字字符串
     * @return
     * @author LiCongLu
     * @date 2020-03-18 10:04
     */
    public static String getPinyinAbbrToLowerCase(String chinese) {
        String abbr = getPinyinAbbr(chinese);
        return abbr != null ? abbr.toLowerCase() : "";
    }

    /**
     * 字符集转换
     *
     * @param chinese 汉字字符串
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:02
     */
    public static Set<String> makeStringByStringSet(String chinese) {
        if (chinese != null && !chinese.trim().equalsIgnoreCase("")) {
            char[] srcChar = chinese.toCharArray();
            String[][] temp = new String[chinese.length()][];
            for (int i = 0; i < srcChar.length; i++) {
                char character = srcChar[i];

                // 是中文或者a-z或者A-Z转换拼音
                if (String.valueOf(character).matches("[\\u4E00-\\u9FA5]+")) {

                    try {
                        temp[i] = PinyinHelper.toHanyuPinyinStringArray(
                                character, getDefaultOutputFormat());

                    } catch (BadHanyuPinyinOutputFormatCombination e) {
                        e.printStackTrace();
                    }
                } else {
                    // 判断是否是字符A-Z及a-z
                    boolean flag = ((int) character >= 65 && (int) character <= 90)
                            || ((int) character >= 97 && (int) character <= 122);
                    if (flag) {
                        temp[i] = new String[]{String.valueOf(srcChar[i])};
                    } else {
                        // 输出空字符串能过滤掉非字母字符
                        //temp[i] = new String[]{""};
                        temp[i] = new String[]{String.valueOf(srcChar[i])};
                    }
                }
            }
            String[] pinyinArray = exchange(temp);
            Set<String> pinYin = new HashSet<String>();
            for (int i = 0; i < pinyinArray.length; i++) {
                pinYin.add(pinyinArray[i]);
            }
            return pinYin;
        }
        return null;
    }

    /**
     * Default Format 默认输出格式
     *
     * @param
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:02
     */
    public static HanyuPinyinOutputFormat getDefaultOutputFormat() {
        HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
        // 小写
        format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
        // 没有音调数字
        format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
        // u显示
        format.setVCharType(HanyuPinyinVCharType.WITH_U_AND_COLON);
        return format;
    }

    /**
     * 交换
     *
     * @param strJaggedArray
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:07
     */
    public static String[] exchange(String[][] strJaggedArray) {
        String[][] temp = doExchange(strJaggedArray);
        return temp[0];
    }

    /**
     * 执行交换
     *
     * @param strJaggedArray
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:09
     */
    private static String[][] doExchange(String[][] strJaggedArray) {
        if (strJaggedArray == null) {
            return strJaggedArray;
        }

        int len = strJaggedArray.length;
        int num2 = 2;
        if (len >= num2) {
            int len1 = strJaggedArray[0].length;
            int len2 = strJaggedArray[1].length;
            int newLen = len1 * len2;
            String[] temp = new String[newLen];
            int Index = 0;
            for (int i = 0; i < len1; i++) {
                for (int j = 0; j < len2; j++) {
                    temp[Index] = capitalize(strJaggedArray[0][i])
                            + capitalize(strJaggedArray[1][j]);
                    Index++;
                }
            }
            String[][] newArray = new String[len - 1][];
            for (int i = num2; i < len; i++) {
                newArray[i - 1] = strJaggedArray[i];
            }
            newArray[0] = temp;
            return doExchange(newArray);
        } else if (len < num2) {
            int len1 = strJaggedArray[0].length;
            for (int i = 0; i < len1; i++) {
                strJaggedArray[0][i] = capitalize(strJaggedArray[0][i]);
            }
            return strJaggedArray;
        } else {
            return strJaggedArray;
        }
    }

    /**
     * 首字母大写
     *
     * @param string
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:01
     */
    public static String capitalize(String string) {
        if (string != null && !string.trim().equalsIgnoreCase("")) {
            char a = 'a';
            char z = 'z';
            char[] chars = string.toCharArray();
            if (chars[0] >= a && chars[0] <= z) {
                chars[0] = (char) (chars[0] - 32);
            }
            String newString = new String(chars);
            return newString;
        }
        return string;
    }


    /**
     * 字符串集合转换字符串(逗号分隔)
     *
     * @param stringSet 字符串集合
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:01
     */
    public static String getPinyinZh_CN(Set<String> stringSet) {
        StringBuilder builder = new StringBuilder();
        if (stringSet != null) {
            int i = 0;
            for (String string : stringSet) {
                if (i == stringSet.size() - 1) {
                    builder.append(string);
                } else {
                    builder.append(string + delimiter);
                }
                i++;
            }
        }
        return builder.toString();
    }


    /**
     * 获取每个拼音的简称
     *
     * @param chinese 汉字字符串
     * @return
     * @author LiCongLu
     * @date 2020-01-20 09:00
     */
    public static String getPinyinConvertAbbr(String chinese) {
        StringBuilder builder = new StringBuilder();
        if (chinese != null && !chinese.trim().equalsIgnoreCase("")) {
            String[] strArray = chinese.split(delimiter);
            for (String str : strArray) {
                // 将字符串转化成char型数组
                char[] arr = str.toCharArray();
                for (int i = 0; i < arr.length; i++) {
                    // 判断是否是大写字母
                    if (arr[i] >= 65 && arr[i] < 91) {
                        builder.append(String.valueOf(arr[i]));
                    }
                }
                builder.append(delimiter);
            }
            String string = builder.toString();
            if (string.endsWith(delimiter)) {
                return string.substring(0, string.length() - 1);
            }
        }
        return builder.toString();
    }

    public static void main(String[] args) {
        String str = "外国血统中国籍人士";
        System.out.println("小写输出：" + getPinyinToLowerCase(str));
        System.out.println("大写输出：" + getPinyinToUpperCase(str));
        System.out.println("首字母大写输出：" + getPinyinFirstToUpperCase(str));
        System.out.println("简拼输出：" + getPinyinAbbr(str));

        try {
            System.out.printf(GsonUtil.toJson(PinyinHelper.toHanyuPinyinStringArray(
                    str.charAt(0), getDefaultOutputFormat())));
        } catch (BadHanyuPinyinOutputFormatCombination badHanyuPinyinOutputFormatCombination) {
            badHanyuPinyinOutputFormatCombination.printStackTrace();
        }
    }
}